package com.coderly.onlinegallerysharingplatform.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.coderly.onlinegallerysharingplatform.common.convention.errorcode.ErrorCode;
import com.coderly.onlinegallerysharingplatform.common.convention.exception.BizException;
import com.coderly.onlinegallerysharingplatform.common.response.Response;
import com.coderly.onlinegallerysharingplatform.enums.PictureReviewStatusEnum;
import com.coderly.onlinegallerysharingplatform.model.dao.entity.PictureDO;
import com.coderly.onlinegallerysharingplatform.model.dto.req.pic.*;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.pic.PictureRespDTO;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.pic.PictureTagCategory;
import com.coderly.onlinegallerysharingplatform.service.PictureService;
import com.coderly.onlinegallerysharingplatform.service.SpaceService;
import com.coderly.onlinegallerysharingplatform.toolkit.ExceptionTrowUtils;
import com.coderly.onlinegallerysharingplatform.toolkit.UserUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class PictureController {

    @Resource
    private PictureService pictureService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private SpaceService spaceService;

    /**
     * 构建本地缓存
     */
    @Deprecated
    private final Cache<String, String> LOCAL_CACHE =
            Caffeine.newBuilder().initialCapacity(1024)
                    .maximumSize(10000L)
                    // 缓存 5 分钟移除
                    .expireAfterWrite(5L, TimeUnit.MINUTES)
                    .build();


    /**
     * 通过文件上传图片
     */
    @PostMapping("/picture/upload")
    //@SaCheckPermission(type = "space", value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Response<PictureRespDTO> uploadPicture(
            @RequestPart("file") MultipartFile multipartFile,
            UploadPictureReqDTO uploadPictureReqDTO) {

        PictureRespDTO pictureRespDTO = pictureService.uploadPicture(multipartFile, uploadPictureReqDTO);
        return Response.success(pictureRespDTO);
    }

    /**
     * 通过URL上传图片
     */
    @PostMapping("/picture/upload/url")
    //@SaCheckPermission(type = "space", value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Response<PictureRespDTO> uploadPictureByUrl(@RequestBody UploadPictureReqDTO uploadPictureReqDTO) {
        PictureRespDTO pictureRespDTO = pictureService.uploadPicture(uploadPictureReqDTO.getUrl(), uploadPictureReqDTO);
        return Response.success(pictureRespDTO);
    }

    /**
     * 删除图片
     */
    @PostMapping("/picture/delete")
    //@SaCheckPermission(type = "space", value = SpaceUserPermissionConstant.PICTURE_DELETE)
    public Response<Boolean> deletePicture(@RequestBody DeletePictureReqDTO deletePictureReqDTO) {
        if (deletePictureReqDTO == null || deletePictureReqDTO.getId() <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        Boolean deletePictureResult = pictureService.deletePicture(deletePictureReqDTO);
        return Response.success(deletePictureResult);
    }

    /**
     * 更新图片-管理员使用
     */
    @PostMapping("/admin/picture/update")
    public Response<Boolean> updatePictureByAdmin(@RequestBody UpdatePictureReqDTO updatePictureReqDTO) {
        if (updatePictureReqDTO == null || updatePictureReqDTO.getId() <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        Boolean updatePictureByAdminResult = pictureService.updatePictureByAdmin(updatePictureReqDTO);
        return Response.success(updatePictureByAdminResult);
    }

    /**
     * 更新图片-用户使用
     */
    @PostMapping("/picture/update")
    // @SaCheckPermission(type = "space", value = SpaceUserPermissionConstant.PICTURE_EDIT)
    public Response<Boolean> updatePictureByUser(@RequestBody UpdatePictureReqDTO updatePictureReqDTO) {
        if (updatePictureReqDTO == null || updatePictureReqDTO.getId() <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        Boolean updatePictureByUserResult = pictureService.updatePictureByUser(updatePictureReqDTO);
        return Response.success(updatePictureByUserResult);
    }

    /**
     * 根据 id 获取图片-管理员使用
     */
    @GetMapping("/admin/picture/get")
    public Response<PictureDO> getPictureByAdminWithId(Long id) {
        ExceptionTrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 查询数据库  
        PictureDO PictureDO = pictureService.getById(id);
        ExceptionTrowUtils.throwIf(PictureDO == null, ErrorCode.NOT_FOUND_ERROR);
        // 获取封装类  
        return Response.success(PictureDO);
    }

    /**
     * 根据 id 获取图片封装类-用户使用
     */
    @GetMapping("/picture/get")
    public Response<PictureRespDTO> getPictureByUserWithId(Long id) {
        ExceptionTrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        PictureRespDTO pictureRespDTO = pictureService.getPictureByUserWithId(id);
        return Response.success(pictureRespDTO);
    }

    /**
     * 分页获取图片列表（仅管理员可用）
     */
    @PostMapping("/admin/picture/list/page")
    public Response<Page<PictureDO>> listPicturePageByAdmin(@RequestBody GetPictureReqDTO getPictureReqDTO) {
        Page<PictureDO> pictureDOPage = pictureService.listPicturePageByAdmin(getPictureReqDTO);
        return Response.success(pictureDOPage);
    }

    /**
     * 分页获取图片列表（封装类）
     * 用户使用
     */
    @PostMapping("/picture/list/page")
    public Response<Page<PictureRespDTO>> listPicturePageByUser(@RequestBody GetPictureReqDTO getPictureReqDTO) {
        // 限制爬虫
        ExceptionTrowUtils.throwIf( getPictureReqDTO.getPageSize() > 20, ErrorCode.PARAMS_ERROR);
        Page<PictureRespDTO> pictureRespDTOPage = pictureService.listPicturePageByUser(getPictureReqDTO);
        return Response.success(pictureRespDTOPage);
    }

    /**
     * 查询指定用户发布在公共图库中已经审核通过的图片列表
     * @param getPictureReqDTO
     * @return
     */
    @PostMapping("/picture/list/my_public_approved/page")
    public Response<Page<PictureRespDTO>> listPublicApprovedPicturePageByUser(@RequestBody GetPictureReqDTO getPictureReqDTO) {
        // 限制爬虫
        ExceptionTrowUtils.throwIf(getPictureReqDTO.getPageSize() > 20, ErrorCode.PARAMS_ERROR);
        // 校验参数
        ExceptionTrowUtils.throwIf(getPictureReqDTO.getUserId() == null, ErrorCode.PARAMS_ERROR);
        Page<PictureRespDTO> pictureRespDTOPage = pictureService.listPublicApprovedPicturePageByUser(getPictureReqDTO);
        return Response.success(pictureRespDTOPage);
    }

    /**
     * 查询指定用户发布在公共图库中所有的图片列表
     * @param getPictureReqDTO
     * @return
     */
    @PostMapping("/picture/list/my_public/page")
    public Response<Page<PictureRespDTO>> listPublicPicturePageByUser(@RequestBody GetPictureReqDTO getPictureReqDTO) {
        // 限制爬虫
        ExceptionTrowUtils.throwIf(getPictureReqDTO.getPageSize() > 20, ErrorCode.PARAMS_ERROR);
        // 校验参数
        ExceptionTrowUtils.throwIf(getPictureReqDTO.getUserId() == null, ErrorCode.PARAMS_ERROR);
        Page<PictureRespDTO> pictureRespDTOPage = pictureService.listPublicPicturePageByUser(getPictureReqDTO);
        return Response.success(pictureRespDTOPage);
    }


    /**
     * 分页获取图片列表（封装类，有缓存）
     * 用户使用
     */
//    @Deprecated
//    @PostMapping("/picture/list/page/vo/cache")
//    public Response<Page<PictureRespDTO>> listPictureVOByPageWithCache(@RequestBody GetPictureReqDTO pictureQueryRequest,
//                                                                       HttpServletRequest request) {
//        long current = pictureQueryRequest.getCurrent();
//        long size = pictureQueryRequest.getPageSize();
//        // 限制爬虫
//        ExceptionTrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
//
//        // 普通用户设置只查看审核通过的图片
//        pictureQueryRequest.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
//
//        // 构建缓存 key
//        String queryCondition = JSONUtil.toJsonStr(pictureQueryRequest);
//        String hashKey = DigestUtils.md5DigestAsHex(queryCondition.getBytes());
//        String cacheKey = "listPictureVOByPage:" + hashKey;
//
//
//        // 1. 查询本地缓存（Caffeine）
//        String cachedValue = LOCAL_CACHE.getIfPresent(cacheKey);
//        if (cachedValue != null) {
//            Page<PictureRespDTO> cachedPage = JSONUtil.toBean(cachedValue, Page.class);
//            return Response.success(cachedPage);
//        }
//
//        // 2. 查询分布式缓存（Redis）
//        try {
//            ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
//            cachedValue = valueOps.get(cacheKey);
//            if (cachedValue != null) {
//                // 如果命中 Redis，存入本地缓存并返回
//                LOCAL_CACHE.put(cacheKey, cachedValue);
//                Page<PictureRespDTO> cachedPage = JSONUtil.toBean(cachedValue, Page.class);
//                return Response.success(cachedPage);
//            }
//        } catch (Exception e) {
//            // Redis 异常时，记录日志但继续执行
//            log.error("Redis cache error: {}", e.getMessage());
//        }
//
//        // 3. 查询数据库
//        Page<PictureDO> picturePage = pictureService.page(new Page<>(current, size),
//                pictureService.buildQueryWrapper(pictureQueryRequest));
//        Page<PictureRespDTO> pictureRespDTOPage = pictureService.getPictureRespDTOList(picturePage);
//        // 4. 更新缓存
//        String cacheValue = JSONUtil.toJsonStr(pictureRespDTOPage);
//        // 更新本地缓存
//        LOCAL_CACHE.put(cacheKey, cacheValue);
//
//        // 异步更新 Redis 缓存，不影响主流程
//        try {
//            CompletableFuture.runAsync(() -> {
//                try {
//                    ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
//                    valueOps.set(cacheKey, cacheValue, 5, TimeUnit.MINUTES);
//                } catch (Exception e) {
//                    log.error("Async Redis cache update error: {}", e.getMessage());
//                }
//            });
//        } catch (Exception e) {
//            log.error("Async task creation error: {}", e.getMessage());
//        }
//
//        return Response.success(pictureRespDTOPage);
//
//    }





    @GetMapping("/picture/tag_category")
    public Response<PictureTagCategory> listPictureTagCategory() {
        PictureTagCategory pictureTagCategory = new PictureTagCategory();
        List<String> tagList = Arrays.asList("热门", "搞笑", "生活", "高清", "艺术", "校园", "背景", "简历", "创意");
        List<String> categoryList = Arrays.asList("模板", "电商", "表情包", "素材", "海报");
        pictureTagCategory.setTagList(tagList);
        pictureTagCategory.setCategoryList(categoryList);
        return Response.success(pictureTagCategory);
    }

    /**
     * 审核图片（仅管理员可用）
     */
    @PostMapping("/admin/picture/review")
    public Response<Boolean> reviewPictureByAdmin(@RequestBody ReviewPictureReqDTO reviewPictureReqDTO) {
        ExceptionTrowUtils.throwIf(reviewPictureReqDTO == null, ErrorCode.PARAMS_ERROR);
        pictureService.reviewPictureByAdmin(reviewPictureReqDTO);
        return Response.success(true);
    }

    @PostMapping("/picture/like")
    public Response<Boolean> likePicture(@RequestBody LikePictureReqDTO likePictureReqDTO) {
        Boolean likePictureResult = pictureService.likePicture(likePictureReqDTO);
        return Response.success(likePictureResult);
    }

    @PostMapping("/picture/unlike")
    public Response<?> unLikePicture(@RequestBody UnLikePictureReqDTO unLikePictureReqDTO) {
        Boolean unLikePictureResult = pictureService.unLikePicture(unLikePictureReqDTO);
        return Response.success(unLikePictureResult);
    }

    @PostMapping("/picture/share")
    public Response<Boolean> sharePicture(@RequestBody SharePictureReqDTO sharePictureReqDTO) {
        Boolean sharePictureResult = pictureService.sharePicture(sharePictureReqDTO);
        return Response.success(sharePictureResult);
    }

    @PostMapping("/picture/unshare")
    public Response<?> unSharePicture(@RequestBody UnSharePictureReqDTO unSharePictureReqDTO) {
        Boolean unSharePictureResult = pictureService.unSharePicture(unSharePictureReqDTO);
        return Response.success(unSharePictureResult);
    }

}
